#include <iostream>
#include <string>
#include <fstream>
#include "../proto/contact_service.pb.h"
#include "../cpp-httplib-master/httplib.h"
#include "../ContactException.h"

#define CONTACTS_HOST "1.12.51.69"
#define CONTACTS_PORT 8082
enum OPTION{
    QUIT = 0,
    ADD_CONTACT,
    DEL_CONTACT,
    FIND_ONE_CONTACT,
    FIND_ALL_CONTACT
};

void menu(){
    std::cout << "————————————————————————————————————————————————————————" << std::endl
              << "————————————————— 请选择对通讯录的操作 ———————————————————" << std::endl
              << "—————————————————— 1、新增联系人 ————————————————————————" << std::endl
              << "—————————————————— 2、删除联系人 ————————————————————————" << std::endl
              << "—————————————————— 3、查看联系人列表 ————————————————————" << std::endl
              << "—————————————————— 4、查看联系人详细信息 —————————————————" << std::endl
              << "—————————————————— 0、退出 —————————————————————————————" << std::endl
              << "————————————————————————————————————————————————————————" << std::endl;
}

void BuildAddContactRequest(contact_service::AddContactRequest *req){
    std::cout << "—————————————————————— 新增联系人 ——————————————————————" << std::endl;
    
    contact_service::ContactInfo* info = new contact_service::ContactInfo();
    
    std::string name;
    std::cout << "请输入姓名: ";
    std::getline(std::cin, name);
    info->set_name(name);

    int age;
    std::cout << "请输入年龄: ";
    std::cin >> age;
    info->set_age(age);
    std::cin.ignore(256, '\n');

    std::string number;
    std::cout << "请输入电话: ";
    std::getline(std::cin, number);
    info->add_number(number);
    

    req->set_allocated_info(info);

    std::cout << "—————————————————————— 添加联系人成功 ——————————————————————" << std::endl;
}

// void TestAddContact(){
//     contact_service::AddContactRequest* contacts = new contact_service::AddContactRequest();
//     // 读取本地人已存在的联系人文件
//     std::fstream input("../contacts.bin", std::ios::in | std::ios::binary);
//     if(!input) std::cout << "contacts.bin not found, creating a new file." << std::endl;
//     else if(!contacts->ParseFromIstream(&input)){    
//         std::cout << "Failed to parse contacts.bin." << std::endl;
//         input.close();
//         return ;
//     }
//     // 向通讯录添加一个联系人
//     BuildAddContactRequest(contacts);


//    // 将联系人信息写入到文件中
//     std::fstream output("../contacts.bin", std::ios::out | std::ios::trunc | std::ios::binary);
//     if(!contacts->SerializeToOstream(&output)){
//         std::cout << "Failed to write contacts.bin." << std::endl;
//         input.close();
//         output.close();
//         return ;
//     }

//     input.close();
//     output.close();
// }


void AddContact(){
    httplib::Client client(CONTACTS_HOST, CONTACTS_PORT);

    // 构造 req
    contact_service::AddContactRequest req;
    BuildAddContactRequest(&req);

    // 序列化 req
    std::string req_str;
    if (!req.SerializeToString(&req_str)){
        throw ContactsException("AddContactRequest 序列化失败! ");
    }

    // 发起 post 调用
    httplib::Result res = client.Post("/contacts/add", req_str, "application/protobuf");
    if (!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 链接失败！错误信息：").append(httplib::to_string(res.error()));
        throw ContactsException(err_desc);
    }

    // 反序列化 resp
    contact_service::AddContactResponse resp;
    bool parse = resp.ParseFromString(res->body);
    // 反序列化也失败了
    if (res->status != 200 && !parse){
        std::string err_desc;
        err_desc.append("/contacts/add 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")");
        throw ContactsException(err_desc);
    }
    else if (res->status != 200){
        std::string err_desc;
        err_desc.append("/contacts/add 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("错误原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    }
    else if (!resp.base_resp().success()){
        std::string err_desc;
        err_desc.append("/contacts/add 结果异常! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("异常原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    }

    // 结果打印
    std::cout << "新增联系人成功，联系人id：" << resp.contact_id() << std::endl;
}

void DelContact() {
    std::string contact_id;
    std::cout << "请输入要删除的联系人ID: ";
    std::cin >> contact_id;
    std::cin.ignore(256, '\n');

    httplib::Client client(CONTACTS_HOST, CONTACTS_PORT);

    // 构造请求
    contact_service::DelContactRequest req;
    req.set_contact_id(contact_id);

    std::string req_str;
    if (!req.SerializeToString(&req_str)) throw ContactsException("DelContactRequest 序列化失败!");

    // 发起 POST 请求
    httplib::Result res = client.Post("/contacts/del", req_str, "application/protobuf");
    if (!res) {
        std::string err_desc;
        err_desc.append("/contacts/del 链接失败！错误信息：").append(httplib::to_string(res.error()));
        throw ContactsException(err_desc);
    }

    // 反序列化响应
    contact_service::DelContactResponse resp;
    bool parse = resp.ParseFromString(res->body);
    if (res->status != 200 && !parse) {
        std::string err_desc;
        err_desc.append("/contacts/del 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")");
        throw ContactsException(err_desc);
    } else if (res->status != 200) {
        std::string err_desc;
        err_desc.append("/contacts/del 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("错误原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    } else if (!resp.base_resp().success()) {
        std::string err_desc;
        err_desc.append("/contacts/del 结果异常! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("异常原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    }

    std::cout << "联系人删除成功, ID: " << resp.contact_id() << std::endl;
}

void Find_ONE_Contact() {
    std::string contact_id;
    std::cout << "请输入要查询的联系人ID: ";
    std::cin >> contact_id;
    std::cin.ignore(256, '\n');

    httplib::Client client(CONTACTS_HOST, CONTACTS_PORT);

    // 构造请求
    contact_service::FindOneContactRequest req;
    req.set_contact_id(contact_id);

    std::string req_str;
    if (!req.SerializeToString(&req_str)) {
        throw ContactsException("FindOneContactRequest 序列化失败!");
    }

    // 发起 POST 请求
    httplib::Result res = client.Post("/contacts/get", req_str, "application/protobuf");
    if (!res) {
        std::string err_desc;
        err_desc.append("/contacts/get 链接失败！错误信息：").append(httplib::to_string(res.error()));
        throw ContactsException(err_desc);
    }

    // 反序列化响应
    contact_service::FindOneContactResponse resp;
    bool parse = resp.ParseFromString(res->body);
    if (res->status != 200 && !parse) {
        std::string err_desc;
        err_desc.append("/contacts/get 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")");
        throw ContactsException(err_desc);
    } else if (res->status != 200) {
        std::string err_desc;
        err_desc.append("/contacts/get 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("错误原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    } else if (!resp.base_resp().success()) {
        std::string err_desc;
        err_desc.append("/contacts/get 结果异常! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("异常原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    }

    // 打印查询结果
    const contact_service::ContactInfo& info = resp.info();
    std::cout << "姓名: " << info.name() << std::endl;
    std::cout << "年龄: " << info.age() << std::endl;
    std::cout << "电话列表: " << std::endl;
    for (int i = 0; i < info.number_size(); ++i) {
        std::cout << "电话 " << i + 1 << ": " << info.number(i) << std::endl;
    }
}

void FIND_ALL_Contact() {
    httplib::Client client(CONTACTS_HOST, CONTACTS_PORT);

    // 构造请求
    contact_service::FindAllContactsResponse req;
    std::string req_str;
    if (!req.SerializeToString(&req_str)) {
        throw ContactsException("FindAllContactsRequest 序列化失败!");
    }

    // 发起 POST 请求
    httplib::Result res = client.Post("/contacts/all", req_str, "application/protobuf");
    if (!res) {
        std::string err_desc;
        err_desc.append("/contacts/all 链接失败！错误信息：").append(httplib::to_string(res.error()));
        throw ContactsException(err_desc);
    }

    // 反序列化响应
    contact_service::FindAllContactsResponse resp;
    bool parse = resp.ParseFromString(res->body);
    if (res->status != 200 && !parse) {
        std::string err_desc;
        err_desc.append("/contacts/all 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")");
        throw ContactsException(err_desc);
    } else if (!resp.base_resp().success()) {
        std::string err_desc;
        err_desc.append("/contacts/all 结果异常! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("异常原因：" + resp.base_resp().error_desc());
        throw ContactsException(err_desc);
    }

    // 打印所有联系人摘要
    std::cout << "所有联系人列表：" << std::endl;
    for (int i = 0; i < resp.contacts_size(); ++i) {
        const contact_service::PeopleInfo& people = resp.contacts(i);
        std::cout << "ID: " << people.contact_id() << ", 姓名: " << people.info().name() << std::endl;
    }
}

int main(){
    while(true){
        menu();
        std::cout << "————> 请选择: ";
        int op;
        std::cin >> op; std::cin.ignore(256, '\n');
        try{
            switch(op){
                case OPTION::QUIT:
                    std::cout << "————> 程序退出" << std::endl;
                    return 0;
                case OPTION::ADD_CONTACT:
                    AddContact();
                    break;
                case OPTION::DEL_CONTACT:
                    DelContact();
                    break;
                case OPTION::FIND_ONE_CONTACT:
                    Find_ONE_Contact();
                    break;
                case OPTION::FIND_ALL_CONTACT:
                    FIND_ALL_Contact();
                    break;
            }
        }catch(const ContactsException& e){
            std::cout << "————> 操作通讯录发送异常" << std::endl;
            std::cout << "————> 异常信息: " << e.what() << std::endl;
        }
    }
    return 0;
} 